#include "device_manager.h"
#include "device_virtual_dev.h"

#include "../../mk_lib/mk_logger.h"



device_manager::device_manager(void)
{
	_dev_number = 0;
	memset(_discover_parameer, 0, sizeof(_discover_parameer));
}

device_manager::~device_manager(void)
{
	clear_devices();
}

int device_manager::discover_devices(char * parameter, char device_pathes[32][256])
{
	g_virtual_discover.enum_and_create_devices("d:\\VMKEY.F");
	strcpy(device_pathes[0], "VMKEY.F");
	return 1;
}

void device_manager::clear_devices()
{
	mk_node * curr_node = _device_list.get_head();
	while(curr_node)
	{
		release_mk_node(curr_node);
		curr_node = curr_node->get_next_node();
	}

	_device_list.remove_all();
}

void device_manager::release_mk_node( mk_node * node )
{
	if(node == NULL)
		return;

	device_base * dev = (device_base*)node->get_data();

	if(dev) delete dev;

	return ;
}

device_base * device_manager::get_device_from_node( mk_node * node )
{
	device_base * dev = (device_base *)node->get_data();

	return dev;
}

int device_manager::enum_and_create_devices( char * parameter )
{
	int removed_num = 0;
	int new_num = 0;
	_dev_number = update_devices(&removed_num, &new_num, parameter);

	return _dev_number;
}


device_base * device_manager::create_device( char * dev_path )
{

	device_base *pdev = get_device_by_path(dev_path);
	if(pdev == NULL)
	{
		pdev = new device_virtual_dev(dev_path);
		_device_list.add(pdev);	
	}

	return pdev;
}


device_base * device_manager::add_new_device(char * dev_path, MK_HANDLE devHandle)
{
	device_base * newDev = NULL;
	newDev = new device_virtual_dev(dev_path);
	_device_list.add(newDev);
	return newDev;
}

device_base * device_manager::get_device( int index )
{
	int i = 0;
	
	if(index > _dev_number - 1)
		return NULL;

	mk_node * curr_node = _device_list.get_head();
	if(curr_node == NULL)
		return NULL;

	if(index == 0)
	{
		return get_device_from_node(curr_node);
	}

	while(curr_node)
	{
		i ++;
		curr_node = curr_node->get_next_node();

		if( i == _dev_number)
			return get_device_from_node(curr_node);
	}

	return NULL;
}

int device_manager::get_device_number()
{
	return _device_list.get_count();
}

int device_manager::update_devices(int * removed_num, int * new_num, char * parameter)
{
	char devPathes[32][256] = {0};
	strcpy(_discover_parameer, parameter);

	int devNumber = discover_devices(_discover_parameer, devPathes);

	* removed_num = detect_removed_devices(devPathes);

	* new_num = detect_new_devices(devNumber, devPathes);

	return devNumber;
}

device_base * device_manager::get_device_by_path( char * dev_path )
{
	MK_POSITION currPos;

	device_base * pDev = get_first_device(currPos);
	if(NULL == pDev)
		return NULL;

	if( strcmp(dev_path, pDev->get_dev_path()) == 0)
	{
		return pDev;
	}

	pDev = get_next_device(currPos);
	while(pDev)
	{
		if( strcmp(dev_path, pDev->get_dev_path()) == 0)
		{
			return pDev;
		}

		pDev = get_next_device(currPos);
	}

	return NULL;
}

device_base * device_manager::get_first_device( MK_POSITION & pos )
{
	mk_node * pNode = _device_list.get_head();
	if(pNode == NULL)
	{
		return NULL;
	}

	pos = (MK_POSITION)pNode;

	return (device_base*)pNode->get_data();
}

device_base * device_manager::get_next_device( MK_POSITION & pos )
{
	if( pos == NULL)
	{
		return get_first_device(pos);
	}

	mk_node * pNode = (mk_node *)pos;

	pNode = pNode->get_next_node();

	if( pNode == NULL)
	{
		return NULL;
	}

	pos = (MK_POSITION) pNode;

	device_base * pDevice = (device_base *)pNode->get_data();

	return pDevice;
}

device_base * device_manager::get_device_by_position( MK_POSITION pos )
{
	mk_node * pNode = (mk_node *)pos;
	if( pNode == NULL)
	{
		return NULL;
	}

	device_base * pDevice = (device_base *)pNode->get_data();

	return pDevice;
}

int device_manager::contains_string( char * strElement, char strColleciton[][256], int collection_size )
{
	for(int i = 0 ; i < collection_size ; i++)
	{
		char * tmp = strColleciton[i];
		if(strcmp(strElement, tmp) == 0)
		{
			return i;
		}
	}

	return -1;
}

int device_manager::detect_removed_devices( char devPathes[][256] )
{
	//detect removed device
	int num = 0;
	MK_POSITION pos;
	device_base * pDev = get_first_device(pos);
	while(pDev)
	{
		if(contains_string(pDev->get_dev_path(), devPathes, 32) < 0) //removed
		{
			pDev->set_dev_state(devStateRemoved);
			num ++;
		}
		else
		{
			pDev->set_dev_state(devStateNormal);
		}

		pDev = get_next_device(pos);
	}

	return num;
}

int device_manager::detect_new_devices(int devNumber, char devPathes[][256])
{
	device_base * pDev = NULL;
	int num = 0;
	//detect new device
	for(int i =  0; i < devNumber ; i ++)
	{
		char * path = devPathes[i];
		pDev = get_device_by_path(path);
		if(pDev == NULL)
		{
			pDev = create_device(path);
			pDev->set_dev_state(devStateNew);
			num ++;
		}
	}	

	return num;
}

int device_manager::destroy_removed_deviced()
{
	MK_POSITION pos;
	device_base * pDev = get_first_device(pos);
	while(pDev)
	{
		if(pDev->get_dev_state() == devStateRemoved)
		{
			_device_list.remove(pDev);
			delete pDev;

			pDev = get_first_device(pos);
			continue;
		}

		pDev = get_next_device(pos);
	}

	return 0;
}

int device_manager::delete_device( MK_POSITION pos )
{
	mk_node * pNode = (mk_node *)pos;
	if( pNode == NULL)
	{
		return 1;
	}

	device_base * pDevice = (device_base *)pNode->get_data();
	_device_list.remove(pDevice);
	delete pDevice;

	return 0;
}
